﻿
using UnityEngine;

namespace Framework
{
    public class Logger
    {
        private static bool _isInited = false;
        private static bool _canLogNormal = true;
        private static bool _canLogWarn = true;
        private static bool _canLogError = true;
        private static readonly string _normalColor = "#" + ColorUtility.ToHtmlStringRGBA(Color.black);
        private static readonly string _warnColor = "#" + ColorUtility.ToHtmlStringRGBA(Color.yellow);
        private static readonly string _errorColor = "#" + ColorUtility.ToHtmlStringRGBA(Color.red);
        private static readonly string _forceColor = "#" + ColorUtility.ToHtmlStringRGBA(Color.cyan);

        private static GeneralCallBack _errorCallback;
        private static GeneralCallBack _logCallback;
        
        public static bool CanLogNormal
        {
            get => _canLogNormal;
            set => _canLogNormal = value;
        }

        public static bool CanLogWarn
        {
            get => _canLogWarn;
            set => _canLogWarn = value;
        }

        public static bool CanLogError
        {
            get => _canLogError;
            set => _canLogError = value;
        }
        
        private static LogFileCollector _logicLogCollector;
        public static void Init()
        {
            if (_isInited) return;
            if (!UnityHelper.IsDebugBuild())
            {
                // 设置日志级别是否显示堆栈信息
                // StackTraceLogType.None：不显示堆栈跟踪
                // StackTraceLogType.ScriptOnly：仅显示脚本相关的堆栈跟踪（过滤掉引擎内部调用）
                // StackTraceLogType.Full：显示完整的堆栈跟踪
                
                Application.SetStackTraceLogType(LogType.Log, StackTraceLogType.None);
                Application.SetStackTraceLogType(LogType.Warning, StackTraceLogType.None);
                Application.SetStackTraceLogType(LogType.Error, StackTraceLogType.ScriptOnly);
                Application.SetStackTraceLogType(LogType.Exception, StackTraceLogType.ScriptOnly);
                Application.SetStackTraceLogType(LogType.Assert, StackTraceLogType.ScriptOnly);
            }
            Application.logMessageReceivedThreaded += CollectLogToFile;
            System.AppDomain.CurrentDomain.UnhandledException += UnhandledException;

            _canLogError = true;
            _canLogWarn = _canLogNormal = UnityHelper.IsDebugBuild();

            _logicLogCollector = new LogFileCollector("logicLog");
            _isInited = true;
        }
        
        private static void CollectLogToFile(string logString, string stackTrace, LogType type)
        {
            try
            {
                string msg = logString + "\n" + stackTrace;
                switch (type)
                {
                    case LogType.Error:
                    case LogType.Exception:
                        _logicLogCollector.CollectErrorLog(msg);
                        if (_errorCallback != null)
                        {
                            GeneralCallBack.Invoke(ref _errorCallback, logString, stackTrace, (int)type);
                        }
                        break;
                    case LogType.Warning:
                        _logicLogCollector.CollectWarnLog(msg);
                        break;
                    case LogType.Log:
                        _logicLogCollector.CollectNormalLog(msg);
                        break;
                    default:
                        break;
                }
                if (_logCallback != null)
                {
                    GeneralCallBack.Invoke(ref _logCallback, logString, stackTrace, (int)type);
                }
            }
            catch (System.Exception exp)
            {
                var msg = exp.Message;
                //磁盘满不用再抛日志
                if (msg.Contains("Disk full") || msg.Contains("Win32 IO returned 112"))
                {
                    return;
                }

                LogError($"SLLogger._CollectLogToFile, type:{type} error:{msg}");
            }
        }

        private static void UnhandledException(object sender, System.UnhandledExceptionEventArgs expArgs)
        {
            if (!_canLogError)
            {
                return;
            }
            try
            {
                System.Exception exp = (System.Exception)expArgs.ExceptionObject;
                if (null != exp)
                {
                    _logicLogCollector.CollectErrorLog(exp.Message + "\n" + exp.StackTrace);
                }
            }
            catch (System.Exception exp)
            {
                Debug.LogException(exp);
            }
        }
        
        /// <summary>
        /// 开关三种级别的log
        /// </summary>
        /// <param name="normal">普通打印</param>
        /// <param name="warn">警告</param>
        /// <param name="error">错误</param>
        public static void SetLog(bool normal, bool warn, bool error)
        {
            _canLogNormal = normal;
            _canLogWarn = warn;
            _canLogError = error;
        }
        
        public static void Log(object msg)
        {
            if (!_canLogNormal)
            {
                return;
            }
            // msg = _ChangeMsgColor(msg, _normalColor);
            Debug.Log(msg);
        }

        public static void ForceLog(object msg)
        {
            if (!_canLogNormal)
            {
                return;
            }
            msg = ChangeMsgColor(msg, _forceColor);
            Debug.Log(msg);
        }

        public static void LogWarning(object msg)
        {
            if (!_canLogWarn)
            {
                return;
            }
            msg = ChangeMsgColor(msg, _warnColor);
            Debug.LogWarning(msg);
        }

        public static void LogError(object msg)
        {
            if (!_canLogError)
            {
                return;
            }
            msg = ChangeMsgColor(msg, _errorColor);
            Debug.LogError(msg);
        }
        
        public static void LogException(System.Exception exp)
        {
            if (!_canLogError)
            {
                return;
            }
            string msg = ChangeMsgColor(exp.Message + "\n" + exp.StackTrace, _errorColor);
            Debug.LogError(msg);
        }
        
        public static void ReportToWeb(string url)
        {
            // string log = _logicLogCollector.GetCurrrentLogStr();
            // SLWebRequest.Instance.PostData(url, log, (bool isSuccerss, string msg) =>
            // {
            //     if (isSuccerss && msg == "success")
            //     {
            //         Log("上传log到 url = " + url + " 成功！");
            //     }
            //     else
            //     {
            //         LogError("上传log到 url = " + url + " 失败！" + msg);
            //     }
            // });
        }
        
        /// <summary>
        /// 修改打印内容的颜色
        /// </summary>
        /// <param name="msg">打印对象</param>
        /// <param name="colorCode">颜色代码</param>
        /// <returns></returns>
        private static string ChangeMsgColor(object msg, string colorCode)
        {
#if UNITY_EDITOR
            return "<color=" + colorCode + ">" + msg.ToString() + "</color>";
#else
            return msg.ToString();
#endif
        }
    }
}